#!/usr/bin/env python3
"""
市场情报模块 - Market Intelligence System
实时监控新闻、政策、宏观经济数据，为AI选股提供情报支持
"""

import requests
import feedparser
import re
import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
import logging
import threading
from concurrent.futures import ThreadPoolExecutor
import time


class NewsImportance(Enum):
    """新闻重要性等级"""
    CRITICAL = ("重大", 5)      # 重大政策、突发事件
    HIGH = ("重要", 4)          # 行业政策、重要数据
    MEDIUM = ("一般", 3)        # 公司公告、行业动态  
    LOW = ("次要", 2)           # 一般新闻
    NOISE = ("噪音", 1)         # 无关新闻


class MarketSentiment(Enum):
    """市场情绪"""
    EXTREMELY_BULLISH = ("极度乐观", 0.9)
    BULLISH = ("乐观", 0.7)
    NEUTRAL = ("中性", 0.5)
    BEARISH = ("悲观", 0.3)
    EXTREMELY_BEARISH = ("极度悲观", 0.1)


@dataclass
class NewsEvent:
    """新闻事件"""
    title: str
    content: str
    source: str
    publish_time: datetime
    importance: NewsImportance
    sentiment_score: float  # -1到1
    keywords: List[str]
    affected_sectors: List[str]
    affected_stocks: List[str]
    confidence: float


@dataclass  
class PolicyEvent:
    """政策事件"""
    title: str
    department: str  # 发布部门
    policy_type: str  # 政策类型
    effective_date: datetime
    impact_sectors: List[str]
    impact_level: int  # 1-5级影响
    bullish_factors: List[str]
    bearish_factors: List[str]


@dataclass
class MacroIndicator:
    """宏观经济指标"""
    name: str
    value: float
    previous_value: float
    change_pct: float
    update_time: datetime
    market_impact: str  # 正面/负面/中性


@dataclass
class MarketIntelligence:
    """市场情报综合报告"""
    overall_sentiment: MarketSentiment
    hot_topics: List[str]
    policy_events: List[PolicyEvent]
    macro_indicators: List[MacroIndicator]
    sector_rotation: Dict[str, float]  # 板块轮动强度
    risk_events: List[str]
    opportunities: List[str]
    intelligence_time: datetime


class NewsSpider:
    """新闻爬虫 - 多源新闻采集"""
    
    def __init__(self):
        self.logger = logging.getLogger('NewsSpider')
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
        
        # 新闻源配置
        self.news_sources = {
            'xinhua': 'http://www.news.cn/fortune/index.htm',
            'people': 'http://finance.people.com.cn/',
            'eastmoney': 'https://finance.eastmoney.com/news/',
            'sina': 'https://finance.sina.com.cn/',
            'securities_times': 'http://www.stcn.com/',
            'securities_daily': 'http://www.zqrb.cn/',
            'csrc': 'http://www.csrc.gov.cn/pub/newsite/',  # 证监会
            'mof': 'http://www.mof.gov.cn/index.htm',        # 财政部
            'pbc': 'http://www.pbc.gov.cn/',                 # 央行
        }
        
        # 关键词库
        self._init_keywords()
    
    def _init_keywords(self):
        """初始化关键词库"""
        # 政策关键词
        self.policy_keywords = [
            "货币政策", "财政政策", "降准", "降息", "加息", "QE", "量化宽松",
            "监管", "改革", "开放", "试点", "规范", "支持", "鼓励", "限制",
            "IPO", "注册制", "退市", "ST", "重组", "并购", "分拆上市"
        ]
        
        # 行业关键词
        self.sector_keywords = {
            "科技": ["人工智能", "AI", "5G", "物联网", "云计算", "大数据", "区块链"],
            "新能源": ["新能源", "电动车", "锂电池", "光伏", "风电", "储能"],
            "医药": ["医药", "生物医药", "疫苗", "创新药", "医疗器械", "CRO"],
            "金融": ["银行", "保险", "证券", "信托", "金融科技"],
            "消费": ["消费", "零售", "餐饮", "旅游", "酒类", "食品"],
            "地产": ["房地产", "地产", "物业", "租赁", "建筑"],
            "周期": ["钢铁", "煤炭", "有色", "化工", "水泥", "建材"]
        }
        
        # 情绪词典
        self.sentiment_words = {
            "positive": ["利好", "上涨", "增长", "突破", "创新", "合作", "订单", "盈利", "超预期", "看好"],
            "negative": ["利空", "下跌", "下滑", "亏损", "风险", "担忧", "压力", "调整", "预警", "看空"]
        }
    
    def crawl_realtime_news(self, hours_back: int = 24) -> List[NewsEvent]:
        """爬取实时新闻"""
        all_news = []
        
        with ThreadPoolExecutor(max_workers=5) as executor:
            futures = {
                executor.submit(self._crawl_government_news): "government",
                executor.submit(self._crawl_financial_news): "financial",
                executor.submit(self._crawl_market_news): "market"
            }
            
            for future in futures:
                try:
                    news_list = future.result(timeout=30)
                    all_news.extend(news_list)
                except Exception as e:
                    self.logger.warning(f"爬取新闻失败: {e}")
        
        # 过滤和排序
        cutoff_time = datetime.now() - timedelta(hours=hours_back)
        recent_news = [news for news in all_news if news.publish_time >= cutoff_time]
        recent_news.sort(key=lambda x: (x.importance.value[1], x.publish_time), reverse=True)
        
        return recent_news[:100]  # 返回最重要的100条新闻
    
    def _crawl_government_news(self) -> List[NewsEvent]:
        """爬取政府官方新闻"""
        news_events = []
        
        # 模拟政策新闻（实际应调用真实API）
        mock_news = [
            {
                'title': '央行宣布降准0.5个百分点，释放长期资金约1万亿元',
                'content': '中国人民银行决定于12月5日下调金融机构存款准备金率0.5个百分点...',
                'source': '央行官网',
                'time': datetime.now() - timedelta(hours=2),
                'importance': NewsImportance.CRITICAL
            },
            {
                'title': '证监会发布全面注册制改革实施方案',
                'content': '为进一步深化资本市场改革，证监会正式发布全面实行股票发行注册制总体实施方案...',
                'source': '证监会',
                'time': datetime.now() - timedelta(hours=6),
                'importance': NewsImportance.CRITICAL
            }
        ]
        
        for news_data in mock_news:
            news_event = NewsEvent(
                title=news_data['title'],
                content=news_data['content'],
                source=news_data['source'],
                publish_time=news_data['time'],
                importance=news_data['importance'],
                sentiment_score=self._analyze_sentiment(news_data['title'] + news_data['content']),
                keywords=self._extract_keywords(news_data['title'] + news_data['content']),
                affected_sectors=self._identify_affected_sectors(news_data['title'] + news_data['content']),
                affected_stocks=self._identify_affected_stocks(news_data['content']),
                confidence=0.9
            )
            news_events.append(news_event)
        
        return news_events
    
    def _crawl_financial_news(self) -> List[NewsEvent]:
        """爬取财经媒体新闻"""
        # 实现财经新闻爬取
        # 这里返回模拟数据
        return []
    
    def _crawl_market_news(self) -> List[NewsEvent]:
        """爬取市场动态新闻"""
        # 实现市场新闻爬取
        # 这里返回模拟数据
        return []
    
    def _analyze_sentiment(self, text: str) -> float:
        """分析文本情绪"""
        positive_count = sum(1 for word in self.sentiment_words['positive'] if word in text)
        negative_count = sum(1 for word in self.sentiment_words['negative'] if word in text)
        
        if positive_count + negative_count == 0:
            return 0.0
        
        sentiment = (positive_count - negative_count) / (positive_count + negative_count)
        return max(-1.0, min(1.0, sentiment))
    
    def _extract_keywords(self, text: str) -> List[str]:
        """提取关键词"""
        keywords = []
        
        # 政策关键词
        for keyword in self.policy_keywords:
            if keyword in text:
                keywords.append(keyword)
        
        # 行业关键词
        for sector, words in self.sector_keywords.items():
            for word in words:
                if word in text:
                    keywords.append(f"{sector}-{word}")
        
        return list(set(keywords))
    
    def _identify_affected_sectors(self, text: str) -> List[str]:
        """识别受影响的行业"""
        affected = []
        for sector, keywords in self.sector_keywords.items():
            if any(keyword in text for keyword in keywords):
                affected.append(sector)
        return affected
    
    def _identify_affected_stocks(self, text: str) -> List[str]:
        """识别受影响的股票"""
        # 使用正则表达式提取股票代码
        stock_pattern = r'(\d{6})'
        stocks = re.findall(stock_pattern, text)
        return list(set(stocks))


class SentimentAnalyzer:
    """情绪分析器"""
    
    def __init__(self):
        self.logger = logging.getLogger('SentimentAnalyzer')
    
    def analyze_market_sentiment(self, news_events: List[NewsEvent]) -> MarketSentiment:
        """分析整体市场情绪"""
        if not news_events:
            return MarketSentiment.NEUTRAL
        
        # 按重要性加权计算情绪
        weighted_sentiment = 0
        total_weight = 0
        
        for news in news_events:
            weight = news.importance.value[1] * news.confidence
            weighted_sentiment += news.sentiment_score * weight
            total_weight += weight
        
        if total_weight == 0:
            return MarketSentiment.NEUTRAL
        
        avg_sentiment = weighted_sentiment / total_weight
        
        # 映射到情绪枚举
        if avg_sentiment >= 0.6:
            return MarketSentiment.EXTREMELY_BULLISH
        elif avg_sentiment >= 0.2:
            return MarketSentiment.BULLISH
        elif avg_sentiment >= -0.2:
            return MarketSentiment.NEUTRAL
        elif avg_sentiment >= -0.6:
            return MarketSentiment.BEARISH
        else:
            return MarketSentiment.EXTREMELY_BEARISH
    
    def analyze_sector_sentiment(self, news_events: List[NewsEvent]) -> Dict[str, float]:
        """分析各行业情绪"""
        sector_sentiment = {}
        
        for news in news_events:
            for sector in news.affected_sectors:
                if sector not in sector_sentiment:
                    sector_sentiment[sector] = []
                
                weight = news.importance.value[1] * news.confidence
                sector_sentiment[sector].append(news.sentiment_score * weight)
        
        # 计算加权平均
        result = {}
        for sector, scores in sector_sentiment.items():
            if scores:
                result[sector] = sum(scores) / len(scores)
        
        return result


class MarketIntelligenceSystem:
    """市场情报系统 - 主控制器"""
    
    def __init__(self):
        self.logger = logging.getLogger('MarketIntelligence')
        self.news_spider = NewsSpider()
        self.sentiment_analyzer = SentimentAnalyzer()
        self.cache = {}  # 缓存情报数据
        self.cache_timeout = 300  # 5分钟缓存
    
    def get_latest_intelligence(self, force_refresh: bool = False) -> MarketIntelligence:
        """获取最新市场情报"""
        cache_key = "latest_intelligence"
        current_time = datetime.now()
        
        # 检查缓存
        if not force_refresh and cache_key in self.cache:
            cached_data, cache_time = self.cache[cache_key]
            if (current_time - cache_time).seconds < self.cache_timeout:
                return cached_data
        
        try:
            # 爬取最新新闻
            news_events = self.news_spider.crawl_realtime_news(24)
            
            # 分析市场情绪
            overall_sentiment = self.sentiment_analyzer.analyze_market_sentiment(news_events)
            sector_sentiment = self.sentiment_analyzer.analyze_sector_sentiment(news_events)
            
            # 提取热点话题
            hot_topics = self._extract_hot_topics(news_events)
            
            # 识别政策事件
            policy_events = self._extract_policy_events(news_events)
            
            # 模拟宏观指标（实际应调用数据接口）
            macro_indicators = self._get_macro_indicators()
            
            # 生成情报报告
            intelligence = MarketIntelligence(
                overall_sentiment=overall_sentiment,
                hot_topics=hot_topics,
                policy_events=policy_events,
                macro_indicators=macro_indicators,
                sector_rotation=sector_sentiment,
                risk_events=self._identify_risk_events(news_events),
                opportunities=self._identify_opportunities(news_events),
                intelligence_time=current_time
            )
            
            # 缓存结果
            self.cache[cache_key] = (intelligence, current_time)
            
            return intelligence
            
        except Exception as e:
            self.logger.error(f"获取市场情报失败: {e}")
            return self._get_default_intelligence()
    
    def _extract_hot_topics(self, news_events: List[NewsEvent]) -> List[str]:
        """提取热点话题"""
        keyword_count = {}
        
        for news in news_events:
            weight = news.importance.value[1]
            for keyword in news.keywords:
                if keyword not in keyword_count:
                    keyword_count[keyword] = 0
                keyword_count[keyword] += weight
        
        # 按热度排序
        sorted_topics = sorted(keyword_count.items(), key=lambda x: x[1], reverse=True)
        return [topic[0] for topic in sorted_topics[:10]]
    
    def _extract_policy_events(self, news_events: List[NewsEvent]) -> List[PolicyEvent]:
        """提取政策事件"""
        policy_events = []
        
        for news in news_events:
            if any(keyword in news.title for keyword in ["政策", "监管", "央行", "证监会", "规定", "办法"]):
                policy_event = PolicyEvent(
                    title=news.title,
                    department=news.source,
                    policy_type="监管政策",
                    effective_date=news.publish_time,
                    impact_sectors=news.affected_sectors,
                    impact_level=news.importance.value[1],
                    bullish_factors=["政策支持", "市场利好"] if news.sentiment_score > 0 else [],
                    bearish_factors=["监管收紧", "政策限制"] if news.sentiment_score < 0 else []
                )
                policy_events.append(policy_event)
        
        return policy_events
    
    def _get_macro_indicators(self) -> List[MacroIndicator]:
        """获取宏观经济指标"""
        # 模拟宏观数据
        indicators = [
            MacroIndicator(
                name="CPI同比",
                value=2.1,
                previous_value=2.3,
                change_pct=-8.7,
                update_time=datetime.now() - timedelta(days=1),
                market_impact="正面"
            ),
            MacroIndicator(
                name="PMI制造业",
                value=51.2,
                previous_value=50.8,
                change_pct=0.8,
                update_time=datetime.now() - timedelta(days=2),
                market_impact="正面"
            ),
            MacroIndicator(
                name="M2货币供应量同比",
                value=11.8,
                previous_value=11.5,
                change_pct=2.6,
                update_time=datetime.now() - timedelta(days=3),
                market_impact="正面"
            )
        ]
        
        return indicators
    
    def _identify_risk_events(self, news_events: List[NewsEvent]) -> List[str]:
        """识别风险事件"""
        risk_keywords = ["风险", "调整", "下跌", "监管", "限制", "警告", "债务", "违约"]
        risks = []
        
        for news in news_events:
            if any(keyword in news.title for keyword in risk_keywords) and news.sentiment_score < -0.3:
                risks.append(f"{news.title[:30]}...")
        
        return risks[:5]
    
    def _identify_opportunities(self, news_events: List[NewsEvent]) -> List[str]:
        """识别投资机会"""
        opportunity_keywords = ["利好", "支持", "鼓励", "发展", "增长", "突破", "合作"]
        opportunities = []
        
        for news in news_events:
            if any(keyword in news.title for keyword in opportunity_keywords) and news.sentiment_score > 0.3:
                opportunities.append(f"{news.title[:30]}...")
        
        return opportunities[:5]
    
    def _get_default_intelligence(self) -> MarketIntelligence:
        """获取默认情报"""
        return MarketIntelligence(
            overall_sentiment=MarketSentiment.NEUTRAL,
            hot_topics=["AI概念", "新能源", "医药"],
            policy_events=[],
            macro_indicators=[],
            sector_rotation={},
            risk_events=[],
            opportunities=[],
            intelligence_time=datetime.now()
        )
    
    def display_intelligence_report(self, intelligence: MarketIntelligence):
        """显示情报报告"""
        print("\n" + "="*80)
        print("🎯 市场情报中心 - Market Intelligence Report")
        print("="*80)
        
        print(f"\n📊 整体市场情绪: {intelligence.overall_sentiment.value[0]}")
        print(f"🕐 情报更新时间: {intelligence.intelligence_time.strftime('%Y-%m-%d %H:%M:%S')}")
        
        print(f"\n🔥 热点话题 TOP {len(intelligence.hot_topics)}:")
        for i, topic in enumerate(intelligence.hot_topics, 1):
            print(f"   {i}. {topic}")
        
        if intelligence.policy_events:
            print(f"\n📋 政策动态 ({len(intelligence.policy_events)}条):")
            for policy in intelligence.policy_events:
                print(f"   • {policy.title}")
                print(f"     发布机构: {policy.department}")
                print(f"     影响级别: {'⭐' * policy.impact_level}")
        
        if intelligence.macro_indicators:
            print(f"\n📈 宏观指标:")
            for indicator in intelligence.macro_indicators:
                direction = "📈" if indicator.change_pct > 0 else "📉"
                print(f"   • {indicator.name}: {indicator.value} {direction} {indicator.change_pct:+.1f}%")
        
        if intelligence.sector_rotation:
            print(f"\n🔄 板块情绪:")
            sorted_sectors = sorted(intelligence.sector_rotation.items(), key=lambda x: x[1], reverse=True)
            for sector, sentiment in sorted_sectors:
                emoji = "🟢" if sentiment > 0.2 else "🔴" if sentiment < -0.2 else "🟡"
                print(f"   {emoji} {sector}: {sentiment:+.2f}")
        
        if intelligence.opportunities:
            print(f"\n💡 投资机会:")
            for opp in intelligence.opportunities:
                print(f"   • {opp}")
        
        if intelligence.risk_events:
            print(f"\n⚠️  风险提示:")
            for risk in intelligence.risk_events:
                print(f"   • {risk}")
        
        print("\n" + "="*80)


def create_market_intelligence() -> MarketIntelligenceSystem:
    """创建市场情报系统实例"""
    return MarketIntelligenceSystem()


if __name__ == "__main__":
    # 测试市场情报系统
    intelligence_system = create_market_intelligence()
    intelligence = intelligence_system.get_latest_intelligence()
    intelligence_system.display_intelligence_report(intelligence) 